package com.boot.database.utils;

import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description 事务 工具类
 * @date 2023/2/6 21:47
 **/

public class TransactionalUtils {

    /**
     * 事务后置处理，可以优化大事务提升连接池性能，尽量保证分布式事务一致性
     * 必须在抛出异常前调用！！！
     *
     * @param runnable 任务
     */
    public static void afterCommit(Runnable runnable) {
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new AfterStatus(runnable, TransactionSynchronization.STATUS_COMMITTED));
        }
    }

    /**
     * 事务后置处理，可以优化大事务提升连接池性能，尽量保证分布式事务一致性
     * 必须在抛出异常前调用！！！
     *
     * @param runnable 任务
     */
    public static void afterRollback(Runnable runnable) {
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new AfterStatus(runnable, TransactionSynchronization.STATUS_ROLLED_BACK));
        }
    }

    /**
     * 事务后置处理，可以优化大事务提升连接池性能，尽量保证分布式事务一致性
     * 必须在抛出异常前调用！！！
     *
     * @param runnable 任务
     */
    public static void afterCompletion(Runnable runnable) {
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new AfterCompletion(runnable));
        }
    }

    public static class AfterCompletion implements TransactionSynchronization {
        private final Runnable runnable;

        public AfterCompletion(Runnable runnable) {
            this.runnable = runnable;
        }

        @Override
        public void afterCompletion(int status) {
            this.runnable.run();
        }
    }

    public static class AfterStatus extends AfterCompletion {
        private final int status;

        public AfterStatus(Runnable runnable, int status) {
            super(runnable);
            this.status = status;
        }

        @Override
        public void afterCompletion(int status) {
            if (status == this.status) {
                super.afterCompletion(status);
            }
        }
    }

}
